/*
 * Copyright (C) Francisco Morero Peyrona. All rights reserved.
 *
 * This software is published under the terms of Open Source
 * License version 1.1, a copy of which has been included with this
 * distribution in the License.txt file.
 */
 
package jdbcmanager.dbtools.dbconnect;

import java.io.*;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

import jdbcmanager.app.*;
import jdbcmanager.awt.*;
import jdbcmanager.swing.*;
import jdbcmanager.swing.help.*;

/**
 * Driver Manager: Add new drivers and Edit existing drivers.
 * 
 * @author Francisco Morero Peyrona
 */

final class JDriverMangerDlg extends JxDialog
{
   // TAB BASIC
   // Panel North
   private JTextField txtName      = new JTextField();
   private JTextField txtSyntax    = new JTextField();
   // Panel Center
   private JList      lstClassPath = new JList( new DefaultListModel() );
   private JButton    btnUp        = null;
   private JButton    btnDown      = null;
   private JButton    btnSeparator = null;
   private JButton    btnAdd       = null;
   private JButton    btnDel       = null;
   // Panel South
   private JTextField txtClassName = new JTextField();
   
   // TAB EXPERT  
   private JTextField txtAgentMeta = new JTextField();
   private JTextField txtAgentSQL  = new JTextField();
   private JTextField txtAgentsJAR = new JTextField();
   
   //-------------------------------------------------------------------------//
   
   JDriverMangerDlg()
   {
      this( "", "", "", null, "", "", "" );
   }
   
   JDriverMangerDlg( String sProductName, String sSyntax, String sClassName, String[] asJAR,
                     String sAgentMetaClassName, String sAgentSQLClassName, String sAgentsJAR )
   {
      super( "Driver Manager" );
    
      init();
      
      // Fill controls
      this.txtName.setText( sProductName );
      this.txtSyntax.setText( sSyntax );
      this.txtClassName.setText( sClassName );
      this.txtAgentMeta.setText( sAgentMetaClassName );
      this.txtAgentSQL.setText( sAgentSQLClassName );
      this.txtAgentsJAR.setText( sAgentsJAR );
      
      if( asJAR != null )
      {
         DefaultListModel model = (DefaultListModel) this.lstClassPath.getModel();
         
         for( int n = 0; n < asJAR.length; n++ )
            model.addElement( asJAR[n] );
            
         if( model.getSize() > 0 )
            this.lstClassPath.setSelectedIndex( 0 );
      }
     
      updateEnabledStatus();
   }
   
   /**
    * 
    * @return
    */
   String getProductName()
   {
      return this.txtName.getText().trim();
   }
   
   /**
    * 
    * @return
    */
   String getAgentMetaDataClassName()
   {
      return this.txtAgentMeta.getText().trim();
   }
   
   /**
    * 
    * @return
    */
   String getAgentSQLClassName()
   {
      return this.txtAgentSQL.getText().trim();
   }
   
   /**
    * JAR file name where Agents are stored (in the case that they are in a JAR: not necessary).
    * 
    * @return JAR file name where Agents are stored
    */
   String getAgentsJAR()
   {
      return this.txtAgentsJAR.getText().trim();
   } 
   
   /**
    * 
    * @return
    */
   String getDriverClassName()
   {
      return this.txtClassName.getText().trim();
   }
   
   /**
    * 
    * @return
    */
   String getConnectionSyntax()
   {
      return this.txtSyntax.getText().trim();
   }
   
   /**
    * 
    * @return
    */
   String[] getJARs()
   {
      DefaultListModel model = (DefaultListModel) this.lstClassPath.getModel();
      Object[]         aObj  = model.toArray();
      String[]         asRet = new String[ aObj.length ];
      
      for( int n = 0; n < asRet.length; n++ )
         asRet[n] = (String) aObj[n];
      
      return asRet;
   }
      
   //-------------------------------------------------------------------------//
   
   protected void onAccept( ActionEvent evt )
   {
      String sError = "";
      
      if( getProductName().length() == 0 )
         sError += "'Driver Name' can not be empty.\n";
         
      if( getJARs().length == 0 )
         sError += "'Path to JAR file(s)' list can not be empty.\n";
      
      if( getDriverClassName().length() == 0 )
         sError += "'Class name' can not be empty.\n";
         
      if( sError.length() > 0 )
         App.showMessage( "Errors found", "Operation can not finish due to following problems:\n"+ sError );
      else
         super.onAccept( evt );
   }
   
   //-------------------------------------------------------------------------//   
   
   protected void onHelp( ActionEvent evt )
   {
      new JHelpDialog( this, "NewEditDriverDialog" );
   }
   
   private void onUpDriver()
   {
      DefaultListModel model = (DefaultListModel) this.lstClassPath.getModel();
      int              nIdx  = this.lstClassPath.getSelectedIndex();
      Object           item  = model.remove( nIdx );
      
      model.add( nIdx-1, item );
      this.lstClassPath.setSelectedIndex( nIdx-1 );
      
      updateEnabledStatus();
   }
   
   private void onDownDriver()
   {
      DefaultListModel model = (DefaultListModel) this.lstClassPath.getModel();
      int              nIdx = this.lstClassPath.getSelectedIndex();
      Object           item = model.remove( nIdx );
      
      model.add( nIdx+1, item );
      this.lstClassPath.setSelectedIndex( nIdx+1 );
      
      updateEnabledStatus();
   }

   private void onAddDriver()
   {
      JFileChooser fc = new JFileChooser();
                   fc.setFileSelectionMode( JFileChooser.FILES_ONLY );
                   fc.setMultiSelectionEnabled( true );
                   fc.addChoosableFileFilter( new JARFileFilter() );
                   fc.setDialogTitle( "Select JAR files for JDBC driver" );

      if( fc.showOpenDialog( App.getFrameMain() ) == JFileChooser.APPROVE_OPTION )
      {
         File[] aFile = fc.getSelectedFiles();
         
         DefaultListModel model = (DefaultListModel) this.lstClassPath.getModel();
         
         for( int n = 0; n < aFile.length; n++ )
            model.addElement( aFile[n].getAbsolutePath() );
      }
      
      updateEnabledStatus();
   }

   private void onDelDriver()
   {
      DefaultListModel model = (DefaultListModel) this.lstClassPath.getModel();
      
      model.remove( this.lstClassPath.getSelectedIndex() );
      
      if( this.lstClassPath.getSelectedIndex() > -1 )
         this.lstClassPath.setSelectedIndex( 0 );
         
      updateEnabledStatus();
   }
   
   // Update enabled for buttons
   private void updateEnabledStatus()
   {
      int nItemCount = this.lstClassPath.getModel().getSize();
      int nSelected  = this.lstClassPath.getSelectedIndex();
      
      this.btnUp.setEnabled( nSelected > 0 );
      this.btnDown.setEnabled( nSelected > -1 && (nSelected < nItemCount - 1) );
      this.btnDel.setEnabled( nSelected != -1 );
   }
   
   private void init()
   {
      // Makes help button available
      btnHelp.setVisible( true );
      
      //---------------------------------------------------------------------------
      // TAB BASIC
      
      // Panel Driver (north) ------------------------------------------------
      JPanel pnlDriver = new JPanel( new SpringLayout() );
             pnlDriver.setBorder( BorderFactory.createTitledBorder( " Driver " ) );
             pnlDriver.add( new JLabel( "Name" ) );
             pnlDriver.add( txtName );
             pnlDriver.add( new JLabel( "Example URL" ) );
             pnlDriver.add( txtSyntax );
             
      SpringUtilities.makeCompactGrid( pnlDriver, 2, 2, 6, 6, 6, 6 );
    
      // Panel Class Path (center) -------------------------------------------
      btnUp   = new JButton( new ImageIcon( JDriverMangerDlg.class.getResource( "images/up_arrow.gif"   ) ) );
      btnUp.setMargin( new Insets( 4,4,4,4 ) );
      btnUp.setToolTipText( "Moves one row up highlighted JAR file in list box" );
      btnDown = new JButton( new ImageIcon( JDriverMangerDlg.class.getResource( "images/down_arrow.gif" ) ) );
      btnDown.setMargin( new Insets( 4,4,4,4 ) );
      btnDown.setToolTipText( "Moves one row down highlighted JAR file in list box" );
      btnAdd  = new JButton( new ImageIcon( JDriverMangerDlg.class.getResource( "images/new.gif"        ) ) );
      btnAdd.setMargin( new Insets( 4,4,4,4 ) );
      btnAdd.setToolTipText( "Open file selection dialog to add JAR files to the list box");
      btnDel  = new JButton( new ImageIcon( JDriverMangerDlg.class.getResource( "images/delete.gif"     ) ) );
      btnDel.setMargin( new Insets( 4,4,4,4 ) );
      btnDel.setToolTipText( "Removes highlighted JAR file from list box" );
      
      btnSeparator = new JButton();
      btnSeparator.setEnabled( false );
      btnSeparator.setOpaque( false );
      btnSeparator.setRequestFocusEnabled( false );
      btnSeparator.setBorderPainted( false );
      btnSeparator.setPreferredSize( new Dimension( 28,28 ) );
      btnSeparator.setMaximumSize( new Dimension( 28,28 ) );
      
      lstClassPath.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
      lstClassPath.addListSelectionListener( new ListSelectionListener()
      { 
         public void valueChanged( ListSelectionEvent evt )   { updateEnabledStatus(); }
      } );     
      
      JPanel pnlClassPath = new JPanel( new BorderLayout() );
             pnlClassPath.setBorder( BorderFactory.createEmptyBorder( 9,0,9,0 ) );
      pnlClassPath.add( new JLabel( " Path to JAR file(s)" ), BorderLayout.NORTH );
             pnlClassPath.add( new JScrollPane( lstClassPath ), BorderLayout.CENTER );
             JPanel pnlEast = new JPanel( new VerticalFlowLayout() );
                    pnlEast.add( btnUp );
                    pnlEast.add( btnDown );
                    pnlEast.add( btnSeparator );
                    pnlEast.add( btnAdd );
                    pnlEast.add( btnDel );
             pnlClassPath.add( pnlEast, BorderLayout.EAST );
             
      btnUp.addActionListener( new ActionListener()
      {
         public void actionPerformed( ActionEvent evt )   { onUpDriver(); }
      } );

      btnDown.addActionListener( new ActionListener()
      {
         public void actionPerformed( ActionEvent evt )   { onDownDriver(); }
      } );

      btnAdd.addActionListener( new ActionListener()
      {
         public void actionPerformed( ActionEvent evt )   { onAddDriver(); }
      } );

      btnDel.addActionListener( new ActionListener()
      {
         public void actionPerformed( ActionEvent evt )   { onDelDriver(); }
      } );
      
      // Panel Class Nane (south) --------------------------------------------
      JPanel pnlClassName = new JPanel( new BorderLayout() );
             pnlClassName.add( new JLabel( "Class name  " ), BorderLayout.WEST   );
             pnlClassName.add( txtClassName                , BorderLayout.CENTER );
      
      // All together
      JPanel pnlBasic = new JPanel( new BorderLayout() );
             pnlBasic.setBorder( BorderFactory.createEmptyBorder( 6,6,6,6 ) );
             pnlBasic.add( pnlDriver   , BorderLayout.NORTH  );
             pnlBasic.add( pnlClassPath, BorderLayout.CENTER );
             pnlBasic.add( pnlClassName, BorderLayout.SOUTH  );
      
      //---------------------------------------------------------------------------
      // TAB EXPERT      
      
      JPanel pnlAgent = new JPanel( new SpringLayout() );
             pnlAgent.add( new JLabel( "MetaData Agent Class" ) );
             pnlAgent.add( txtAgentMeta );
             pnlAgent.add( new JLabel( "SQL Agent Class" ) );
             pnlAgent.add( txtAgentSQL );
             pnlAgent.add( new JLabel( "Agents JAR (if any)" ) );
             pnlAgent.add( txtAgentsJAR );
             SpringUtilities.makeCompactGrid( pnlAgent, 3, 2, 6, 6, 6, 6 );
      
      JPanel pnlExpert = new JPanel( new BorderLayout() );
             pnlExpert.setBorder( BorderFactory.createEmptyBorder( 6,6,6,6 ) );
             pnlExpert.add( pnlAgent, BorderLayout.NORTH );
             pnlExpert.add( new JPanelNote( "These settings are used in very rare occasions.\n"+
                                            "And default values will fit for almost all necessities.\n"+
                                            "Do not change it unless you know exactly what you are doing." ), 
                            BorderLayout.SOUTH );
                            
      //---------------------------------------------------------------------------
      // ASSEMBLE TABS
      
      JTabbedPane tabPane = new JTabbedPane();
                  tabPane.addTab( "Basic" , pnlBasic  );
                  tabPane.addTab( "Expert", pnlExpert );
      getContentPane().add( tabPane, BorderLayout.CENTER );
   }
   
   //-------------------------------------------------------------------------//
   // INNER CLASS: JARFileFilter
   //-------------------------------------------------------------------------//
   private final class JARFileFilter extends javax.swing.filechooser.FileFilter
   {
      public boolean accept( File f )
      {
         String sName = f.getName().toUpperCase();
         
         return f.isDirectory() || sName.endsWith( ".JAR" ) || sName.endsWith( ".ZIP" );
      }
      
      public String getDescription()
      {
         return "JAR and ZIP files";
      }
   }
}
